package com.duobaoyu.dby.supply.biz.exception;

import com.alibaba.tuna.client.api.MessageProcessException;
import com.duobaoyu.dby.channel.adapter.exception.SupplyChannelException;
import com.duobaoyu.dby.common.core.util.R;
import com.duobaoyu.dby.common.feign.sentinel.handle.GlobalBizExceptionHandler;
import com.duobaoyu.dby.supply.core.common.annotation.ResponseAdvice;
import com.duobaoyu.dby.supply.core.common.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

/**
 * @author liyang
 * @version 1.0.0
 * @ClassName GlobalExceptionHandler
 * @Description 全局异常处理器
 * @createTime 16:05:00 2023/10/18
 */
@Slf4j
@ResponseAdvice
@RestControllerAdvice
public class GlobalExceptionHandler extends GlobalBizExceptionHandler {

    @Override
    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public R handleBodyValidException(MethodArgumentNotValidException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        log.error("参数绑定异常,MethodArgumentNotValidException ,msg = {}", ExceptionUtils.getStackTrace(exception));
        return R.failed(fieldErrors.stream().findFirst().map(FieldError::getDefaultMessage).orElse(null), HttpServletResponse.SC_BAD_REQUEST);
    }

    @Override
    @ExceptionHandler({BindException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R bindExceptionHandler(BindException exception) {
        List<FieldError> fieldErrors = exception.getBindingResult().getFieldErrors();
        log.error("参数绑定异常,ex = {}", ExceptionUtils.getStackTrace(exception));
        return R.failed(fieldErrors.stream().findFirst().map(FieldError::getDefaultMessage).orElse(null),HttpServletResponse.SC_BAD_REQUEST);
    }


    @ResponseStatus(HttpStatus.OK)
    @ExceptionHandler({SupplyChainBizException.class, CustomException.class})
    public R supplyChainApiException(CustomException e) {
        log.error("message:{},data:{}", "全局异常拦截", ExceptionUtils.getStackTrace(e));
        return R.errorDate(e.getData(), e.getCode(), e.getMessage());
    }

    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler({SupplyChannelException.class})
    public R channelException(SupplyChannelException e) {
        log.error("message:{},data:{}", "全局 渠道对接 异常拦截",ExceptionUtils.getStackTrace(e));
        return R.errorDate(e.getData(), e.getCode(), e.getMessage());
    }

    @Override
    @ExceptionHandler({Exception.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R handleGlobalException(Exception e) {
        log.error("message:{},data:{}", "全局异常拦截", ExceptionUtils.getStackTrace(e));
        if (e instanceof MessageProcessException) {
            throw ((MessageProcessException) e);
        }

        if (e instanceof IllegalArgumentException) {
            log.error("message:{},data:{}", "全局异常拦截", ExceptionUtils.getStackTrace(e));
            return R.failed(StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : "供应链响应异常");
        }

        if(e instanceof IllegalStateException) {
            return R.failed(StringUtils.isNotBlank(e.getMessage()) ? e.getMessage() : "供应链响应异常");
        }

        log.error("message:{},data:{}", "全局异常拦截", ExceptionUtils.getStackTrace(e));
        return R.failed("供应链响应异常");
    }
}
